<!DOCTYPE html>
<html>
    <head>
        <title>代码工作量统计小工具</title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <!--<link href="http://lib.sinaapp.com/js/jquery-mobile/1.2.0/jquery.mobile-1.2.0.min.css" rel="stylesheet" type="text/css" />-->
        <!--<script src="http://lib.sinaapp.com/js/jquery/1.9.0/jquery.min.js"></script>-->
        <!--<script src="jquery.mobile-1.2.0.min.js"></script>-->

        <link rel="stylesheet" href="http://code.jquery.com/mobile/1.3.0/jquery.mobile-1.3.0.min.css">
        <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
        <script src="http://code.jquery.com/mobile/1.3.0/jquery.mobile-1.3.0.min.js"></script>

        <script src="http://code.highcharts.com/highcharts.js"></script>
        <script src="http://code.highcharts.com/modules/exporting.js"></script>
        <script>
            $(document).ready(function(){
                //++ 忽略统计的路径 ++++++++++++++++++++++++++++++++++++++++++++
                var ignore = [
                    '/branches/ThinkPHP',
                    '/branches/1.0/libs/ckeditor',
                    '/branches/1.0/logs',
                    '/branches/1.0/statics/datepicker',
                    '/branches/1.0/statics/js/ui',
                    '/branches/2.0/libs/ckeditor',
                    '/branches/2.0/logs',
                    '/branches/2.0/statics/datepicker',
                    '/branches/2.0/statics/js/ui',
                    '/branches/3.0/libs/ckeditor',
                    '/branches/3.0/logs',
                    '/branches/3.0/statics/datepicker',
                    '/branches/3.0/statics/js/ui',
                    '/branches/3.0/kernel/smarty',
                    '/branches/3.0/statics/swfupload',
                    '/branches/4.0/libs/ckeditor',
                    '/branches/4.0/logs',
                    '/branches/4.0/statics/datepicker',
                    '/branches/4.0/statics/js/ui',
                    '/branches/4.0/kernel/smarty',
                    '/branches/4.0/statics/swfupload',
                    '/branches/4.0/kernel/caches',
                    '/branches/5.0/libs/ckeditor',
                    '/branches/5.0/logs',
                    '/branches/5.0/statics/datepicker',
                    '/branches/5.0/statics/js/ui',
                    '/branches/5.0/kernel/smarty',
                    '/branches/5.0/statics/swfupload',
                    '/branches/5.0/kernel/caches',
                    '/branches/6.0/libs/ckeditor',
                    '/branches/6.0/logs',
                    '/branches/6.0/statics/datepicker',
                    '/branches/6.0/statics/js/ui',
                    '/branches/6.0/kernel/smarty',
                    '/branches/6.0/statics/swfupload',
                    '/branches/6.0/kernel/caches',
                    '/branches/6.5/libs/ckeditor',
                    '/branches/6.5/logs',
                    '/branches/6.5/statics/datepicker',
                    '/branches/6.5/statics/js/ui',
                    '/branches/6.5/kernel/smarty',
                    '/branches/6.5/statics/swfupload',
                    '/branches/6.5/kernel/caches',
                    '/branches/6.5/caches',
                    '/branches/7.0/Public/Lib',
                    '/branches/7.0/Lib/Common/PHPExcel',
                    '/branches/office/Vendor'
                ];
                //在职的程序员，用于生成报表
                var authors = '"zuojh","terry","sungx","mithern","listen","zhanghao","liufeng","jerry","huancaijin"';
                //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
                var db = openDatabase('works','','工作量统计数据库',102400);
                db.transaction(function(tx){
                    //tx.executeSql('drop table IF EXISTS authors');
                    //tx.executeSql('drop table IF EXISTS files');
                    //初始化数据库用户表 authors
                    //主键id，svn作者名，svn版本号，记录时间，文件路径，有效代码行数，SVN注释信息
                    tx.executeSql('CREATE TABLE IF NOT EXISTS authors (a_id unique, a_name, a_version, a_time , a_files, a_code, a_comments)');
                    //初始化文件系统表 files
                    //主键id，文件路径，总代码行，空行，注释行，文件最近更新时间，文件大小
                    tx.executeSql('CREATE TABLE IF NOT EXISTS files (f_id unique, f_files, f_lines, f_emptys, f_comments, f_time, f_size)');

                    //var insertData = ["sungx", "10551", "2013-1-3 11:23:46", "/branches/tongfangpc/libs/GY_Goods.class.php", 2, "去掉商品同步时自动将市场价清零的问题"];
                    //var insertSql = "insert into authors (a_name, a_version, a_time , a_files, a_code, a_comments) values (?,?,?,?,?,?)";
                    //tx.executeSql(insertSql, insertData);
                });

                //+++ 显示默认列表 +++++++++++++++++++++++++++++++++++++++++++++
                showList(db,0,0,0);

                //+++ 显示月份表格 +++++++++++++++++++++++++++++++++++++++++++++
                var chart;
                var chartData = getChartsData(db,authors);
                setTimeout(function(){
                    console.log(chartData);
                    chart = new Highcharts.Chart({
                        chart: {
                            renderTo: 'container',
                            type: 'spline'
                        },
                        title: {
                            text: '月度报表'
                        },
                        subtitle: {
                            text: '数据来源: https://fx.guanyisoft.com/shopplus/'
                        },
                        xAxis: {
                            categories: chartData.categories
                        },
                        yAxis: {
                            title: {
                                text: '有效代码量'
                            },
                            labels: {
                                formatter: function() {
                                    return this.value +'行'
                                }
                            }
                        },
                        tooltip: {
                            crosshairs: true,
                            shared: true
                        },
                        plotOptions: {
                            spline: {
                                marker: {
                                    radius: 4,
                                    lineColor: '#666666',
                                    lineWidth: 1
                                }
                            }
                        },
                        series: chartData.series
                    });
                },3000);

                //+++ 显示忽略列表 +++++++++++++++++++++++++++++++++++++++++++++
                var ignoreInnerHtml = '';
                for(var i = 0; i<ignore.length; i++){
                    ignoreInnerHtml = ignoreInnerHtml + '<li>' + ignore[i] + '</li>';
                }
                $('#ignoreFiles').html(ignoreInnerHtml);

                //+++ 更新操作 +++++++++++++++++++++++++++++++++++++++++++++++++
                $('#button_refresh').click(function(){
                    //查找SVN更新信息，返回json数组
                    $('#refresh_rate_1').html('获取中...');
                    $('#refresh_rate_2_total').html(0);
                    $('#refresh_rate_2_now').html(0);
                    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
                    var updateStart = $('#updateStart').val();
                    var updateEnd = $('#updateEnd').val();
                    $('#dialogPageHeader').html(updateStart + '~' + updateEnd + '数据更新中');

                    $.get('works.php',{act:'refresh',updateStart:updateStart,updateEnd:updateEnd},function(data){
                        if(data.status==0){
                            $('#refresh_rate_1').html('0%');
                            //查询总量
                            var logs = data.result.logentry;
                            var lg = data.result.logentry.length;
                            //循环发送请求查找每次修改的文件
                            //console.log(logs);
                            //console.log(lg);
                            var total = 0;
                            for(var i=0; i<lg; i++){
                                //@todo 延迟发送ajax请求，每秒发送20条
                                var dat = logs[i];

                                if(dat.paths.path[0] != '/'){
                                    //console.log('数组0'+dat.paths.path[0]);
                                    $.each(dat.paths.path, function(k){
                                        total++;
                                        //console.log(dat.paths.path[0]);
                                        //console.log(dat.paths.path[k]);
                                        findSvnDiff(db, dat['@attributes'].revision, dat.paths.path[k], dat, total*50);
                                        //findSvnDiff(db, logs[i]['@attributes'].revision, logs[i].paths.path[k], logs[i]);
                                    });
                                }else{
                                    total++;
                                    //console.log('字串'+dat.paths.path);
                                    //console.log(logs[i].paths.path.constructor);
                                    //console.log(dat);
                                    findSvnDiff(db, dat['@attributes'].revision, dat.paths.path, dat, total*50);
                                    //findSvnDiff(db, logs[i]['@attributes'].revision, logs[i].paths.path, logs[i]);
                                }
                                $("#refresh_rate_2_total").html(total);
                            }
                        }else{
                            $('#refresh_rate_1').html('获取失败!')
                        }
                    },'json');

                    //查找总项目代码变更信息

                });

                //+++ 显示全部统计列表 +++++++++++++++++++++++++++++++++++++++++
                $('#button_show_all').click(function(){
                    showList(db,0,0,2);
                });

                //+++ 数据统计列表查询操作 ++++++++++++++++++++++++++++++++++++++
                $("#countSearch").click(function(){
                    var timer1 = $('#countStart').val();
                    var timer2 = $('#countEnd').val();
                    var countType = $('#countType').val();
                    showList(db,timer1,timer2,countType);
                });

                //+++ 修正统计值 +++++++++++++++++++++++++++++++++++++++++++++++
                $('#button_fix').click(function(){
                    db.transaction(function(tx){
                        var cond = ' ';
                        for(var i = 0; i<ignore.length; i++){
                            if(i!=0)
                                cond = cond + ' or ';
                            cond = cond + ' a_files like "'+ignore[i]+'%"';
                        }
                        var sql = "update authors set a_code = 1.5 where ( "+cond+" ) and a_code > 0";
                        console.log(sql);
                        tx.executeSql(sql);
                    });
                });

                //+++ 刷新错误信息 +++++++++++++++++++++++++++++++++++++++++++++
                $("#button_error_refresh").click(function(){
                    showSvnError(db);
                });

                //+++ 删除本地缓存 +++++++++++++++++++++++++++++++++++++++++++++
                $("#button_clear").click(function(){
                    db.transaction(function(tx){
                        var sql = "delete from authors ";
                        tx.executeSql(sql);
                    });
                });

            });

            //+++ 方法库 ++++++++++++++++++++++++++++++++++++++++++++++++++++++

            /**
             * 查找本地webSql里面SVN单个版本的变动信息
             * @param db object 数据连接
             * @param version int 版本号
             * @param file string 文件路径
             * @param dat object 单个版本完整json数据
             */
            function findSvnDiff(db, version, file, dat, timer){
                db.transaction(function(tx){
                    var sql = "select * from authors where a_version = ? and a_files = ?";
                    tx.executeSql(sql,[version,file],function(tx, results){
                        if(results && results.rows && 0 < results.rows.length) {
                            //console.log('跳过：');
                            //console.log(version+'@@'+file);
                            //结果不为空，表明已经处理过，不再处理
                            var refresh_rate_2_now = $("#refresh_rate_2_now").html();
                            var refresh_rate_2_total = $("#refresh_rate_2_total").html();
                            var percent = Math.round( (refresh_rate_2_now / refresh_rate_2_total) * 100 );
                            refresh_rate_2_now++;
                            $("#refresh_rate_2_now").html(refresh_rate_2_now);
                            $('#refresh_rate_1').html(percent + '%');

                        }else{
                            //结果为空，需要异步请求数据然后插入
                            //数据为(a_id unique, a_name, a_version, a_time, a_cate, a_files, a_code, a_comments)
                            var a_name = dat.author;
                            var date = new Date(dat.date);

                            var month = date.getMonth()+1;
                            var day = date.getDate();
                            var hours = date.getHours();
                            var minutes = date.getMinutes();
                            var seconds = date.getSeconds();
                            month = (month < 10) ? '0' + month : month;
                            day = (day < 10) ? '0' + day : day;
                            hours = (hours < 10) ? '0' + hours : hours;
                            minutes = (minutes < 10) ? '0' + minutes : minutes;
                            seconds = (seconds < 10) ? '0' + seconds : seconds;

                            var a_time = date.getFullYear() + '-' + month + '-' + day + ' ' + hours + ':' + minutes + ':' + seconds;
                            var a_comments = dat.msg;

                            //console.log('获取：');
                            //console.log(version+'@@'+file);
                            //console.log(dat);
                            setTimeout(function(){
                                $.get('works.php',{act:'diff',version:version,url:file},function(data){
                                    //console.log(data.result+'@@'+a_name+'@@'+file);
                                    var insertData = [a_name, version, a_time, file, data.result, a_comments];
                                    //if(data.result==0)
                                    console.log(insertData);
                                    var insertSql = "insert into authors (a_name, a_version, a_time , a_files, a_code, a_comments) values (?,?,?,?,?,?)";
                                    saveSvnDiff(db,insertSql,insertData);
                                },'json');
                            },timer);
                        }
                    },function(tx, error){
                        console.log(error);
                    });

                });
            }

            //获取服务器上SVN单个版本的变动信息
            function saveSvnDiff(db,insertSql,insertData){
                db.transaction(function(tx){
                    tx.executeSql(insertSql, insertData);
                    //插入执行成功后的回调方法
                    var refresh_rate_2_now = $("#refresh_rate_2_now").html();
                    var refresh_rate_2_total = $("#refresh_rate_2_total").html();
                    var percent = Math.round( (refresh_rate_2_now / refresh_rate_2_total) * 100 );
                    refresh_rate_2_now++;
                    $("#refresh_rate_2_now").html(refresh_rate_2_now);
                    $('#refresh_rate_1').html(percent + '%');
                });
            }

            //统计可能出现的分析错误
            function showSvnError(db){
                db.transaction(function(tx){
                    var sql = 'select a_files,count(a_files) as total FROM authors where a_code = 0 and (a_files like "%.php" or a_files like "%.html" or a_files like "%.htm" or a_files like "%.js" or a_files like "%.css")  group by a_files having count(a_files) > 1 order by a_files desc';
                    tx.executeSql(sql, [], function(tx,results){
                        //查询成功后的回调方法
                        $("#ulErrorList").html('');
                        for(i = 0; i < results.rows.length; i++){
                            var a_files = results.rows.item(i).a_files;
                            var total = results.rows.item(i).total;
                            var innerHtml = '<li>'+a_files+'<span class="ui-li-count">'+total+'</span></li>';
                            $("#ulErrorList").append(innerHtml);
                        }
                        $("#ulErrorList" ).listview("refresh");
                    });
                });
            }

            //显示统计列表
            function showList(db,timer1,timer2,type){
                if(type==0){
                    var codetype = '  a_files like "%.php" ';
                }else if(type==1){
                    var codetype = ' ( a_files like "%.php" or a_files like "%.js" or a_files like "%.html" or a_files like "%.htm" or a_files like "%.css" ) ';
                }else{
                    var codetype = ' 1 ';
                }
                if(timer1==0 && timer2==0){
                    $('#countCondition').html('统计全部');
                    var sql = "select a_name, sum(a_code) as total, count(a_files) as times from authors where " + codetype + " and a_code < 1000 group by a_name order by total desc";
                    var cond = [];
                }else{
                    $('#countCondition').html(timer1+'~'+timer2);
                    var sql = "select a_name, sum(a_code) as total, count(a_files) as times from authors where " + codetype + " and a_code < 1000 and datetime(a_time) >= datetime(?) and datetime(a_time) <= datetime(?) group by a_name order by total desc";
                    var cond = [timer1,timer2];
                }
                db.transaction(function(tx){
                    tx.executeSql(sql,cond,function(tx, results){
                        //console.log(sql);
                        if(results && results.rows && 0 < results.rows.length) {
                            $("#tableCountList > tbody").html('');
                            var codes = 0;
                            var times = 0;
                            for(i = 0; i < results.rows.length; i++){
                                times += results.rows.item(i).times;
                                codes += results.rows.item(i).total;
                            }
                            for(i = 0; i < results.rows.length; i++){
                                //console.log(results.rows.item(i));
                                var a_name = results.rows.item(i).a_name;
                                var a_times = results.rows.item(i).times;
                                var a_code = results.rows.item(i).total;
                                var a_percent = Math.round((a_code / codes) * 100) + '%';

                                var innerHtml = '<tr><th>'+(i+1)+'</th><th>'+a_name+'</th><td>'+a_times+'</td><td>'+Math.round(a_code)+'</td><td>'+a_percent+'</td></tr>';
                                $("#tableCountList > tbody").append(innerHtml);
                            }
                            innerHtml = '<tr><th>共计</th><td></td><td>'+times+'</td><td>'+Math.round(codes)+'</td><td>&nbsp;</td></tr>';
                            $("#tableCountList > tbody").append(innerHtml);
                        }else{
                            $("#tableCountList > tbody").html('<tr><th>没有查到结果!</th><td></td><td></td><td></td><td></td></tr>');
                        }
                    });
                });
            }

            //生成图表数据
            function getChartsData(db,coder){
                var categories = [];
                var series = [];
                var names = [];

                db.transaction(function(tx){
                    //取得月份数据
                    var sql = 'select substr(a_time,1,7) as months from authors group by substr(a_time,1,7) order by a_time';
                    tx.executeSql(sql,[],function(tx,results){
                        if(results && results.rows && 0 < results.rows.length) {
                            for(i = 0; i < results.rows.length; i++){
                                categories[i] = results.rows.item(i).months;
                            }
                        }

                    });

                    //取得作者数据
                    if( coder == '' ){
                        var sql = 'select a_name FROM authors where a_code < 1000 group by a_name order by sum(a_code) desc';
                    }else{
                        var sql = 'select a_name FROM authors where a_code < 1000 and a_name in (' + coder + ') group by a_name order by sum(a_code) desc';
                        //console.log(sql);
                    }

                    tx.executeSql(sql,[],function(tx,results){
                        if(results && results.rows && 0 < results.rows.length) {
                            for(i = 0; i < results.rows.length; i++){
                                names[i] = results.rows.item(i).a_name;
                            }
                        }
                    });

                    //取得每个作者每个月的数据
                    var sql = 'select a_name,sum(a_code) as code,substr(a_time,1,7) as months from authors where a_code < 1000 group by a_name,substr(a_time,1,7) order by a_name,a_time';
                    tx.executeSql(sql,[],function(tx,results){
                        if(results && results.rows && 0 < results.rows.length) {
                            for(c = 0; c < names.length; c++){
                                var data = [];
                                for(m = 0; m < categories.length; m++){
                                    data[m] = 0;
                                    for(i = 0; i < results.rows.length; i++){
                                        if (categories[m]==results.rows.item(i).months && names[c]==results.rows.item(i).a_name){
                                            data[m] = Math.round(results.rows.item(i).code);
                                        }
                                    }
                                }
                                series[c] = {name:names[c],data:data}
                            }
                        }

                    });

                });

                return {'categories':categories,'series':series};

            }
        </script>

        <script>
            /**
             * Grid theme for Highcharts JS
             * @author Torstein Hønsi
             */

            Highcharts.theme = {
                colors: ['#058DC7', '#50B432', '#ED561B', '#DDDF00', '#24CBE5', '#64E572', '#FF9655', '#FFF263', '#6AF9C4'],
                chart: {
                    backgroundColor: {
                        linearGradient: [0, 0, 500, 500],
                        stops: [
                            [0, 'rgb(255, 255, 255)'],
                            [1, 'rgb(240, 240, 255)']
                        ]
                    },
                    borderWidth: 2,
                    plotBackgroundColor: 'rgba(255, 255, 255, .9)',
                    plotShadow: true,
                    plotBorderWidth: 1
                },
                title: {
                    style: {
                        color: '#000',
                        font: 'bold 16px "Trebuchet MS", Verdana, sans-serif'
                    }
                },
                subtitle: {
                    style: {
                        color: '#666666',
                        font: 'bold 12px "Trebuchet MS", Verdana, sans-serif'
                    }
                },
                xAxis: {
                    gridLineWidth: 1,
                    lineColor: '#000',
                    tickColor: '#000',
                    labels: {
                        style: {
                            color: '#000',
                            font: '11px Trebuchet MS, Verdana, sans-serif'
                        }
                    },
                    title: {
                        style: {
                            color: '#333',
                            fontWeight: 'bold',
                            fontSize: '12px',
                            fontFamily: 'Trebuchet MS, Verdana, sans-serif'

                        }
                    }
                },
                yAxis: {
                    minorTickInterval: 'auto',
                    lineColor: '#000',
                    lineWidth: 1,
                    tickWidth: 1,
                    tickColor: '#000',
                    labels: {
                        style: {
                            color: '#000',
                            font: '11px Trebuchet MS, Verdana, sans-serif'
                        }
                    },
                    title: {
                        style: {
                            color: '#333',
                            fontWeight: 'bold',
                            fontSize: '12px',
                            fontFamily: 'Trebuchet MS, Verdana, sans-serif'
                        }
                    }
                },
                legend: {
                    itemStyle: {
                        font: '9pt Trebuchet MS, Verdana, sans-serif',
                        color: 'black'

                    },
                    itemHoverStyle: {
                        color: '#039'
                    },
                    itemHiddenStyle: {
                        color: 'gray'
                    }
                },
                labels: {
                    style: {
                        color: '#99b'
                    }
                }
            };

            // Apply the theme
            var highchartsOptions = Highcharts.setOptions(Highcharts.theme);
        </script>
    </head>
    <body>
        <!-- 默认工作量首页 ---------------------------------------------------->
        <div data-role="page" id="pageCountList">
            <div data-role="header">
                <h1>代码工作量统计小工具</h1>
                <div data-role="navbar" data-iconpos="left">
                    <ul>
                        <li><a href="#pageCountList" class="ui-btn-active" data-icon="grid">SVN工作日志</a></li>
                        <li><a href="#pageCodeList" data-icon="search">月度报表</a></li>
                        <li><a href="#pageCodeUpdate" data-icon="refresh">更新数据源</a></li>
                        <li><a href="#pageHelp" data-icon="alert">使用帮助</a></li>
                    </ul>
                </div>
            </div>
            <!--<div data-role="content">
                <div data-role="controlgroup" data-type="horizontal">
                    <a href="javascript:void(0);" data-role="button" data-icon="grid">SVN工作日志</a>
                    <a href="javascript:void(0);" data-role="button" data-icon="grid">月度报表</a>
                    <a href="javascript:void(0);" data-role="button" data-icon="search">高级查询</a>
                    <a href="#dialogPage" data-role="button" data-icon="refresh" id="button_refresh" title="更新" data-rel="dialog">更新统计</a>
                </div>
            </div>-->

            <div data-role="content">
                <div data-role="controlgroup" data-type="horizontal" data-inline="true">
                    <a href="#panelCount" data-role="button" data-icon="bars">统计条件</a>
                    <a href="#" id="button_show_all" data-role="button" data-icon="grid">显示全部</a>
                    <a href="#" id="button_fix" data-role="button" data-icon="alert">统计值修正</a>
                </div>
                <em id="countCondition">全部</em>
                <table data-role="table" id="tableCountList" data-mode="" class="table-stroke">
                    <thead>
                        <tr>
                            <th data-priority="1">排名</th>
                            <th data-priority="2">用户名</th>
                            <th data-priority="persist">代码修订次数</th>
                            <th data-priority="3">代码提交量</th>
                            <th data-priority="4">约百分比</th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr>
                            <th>请查询</th>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                        </tr>
                    </tbody>
                </table>
            </div>

            <div data-role="panel" id="panelCount" data-theme="b">
                <div class="panel-content">
                    <h3>起始时间</h3>
                    <p><input type="date" name="countStart" id="countStart" value="" /></p>
                    <h3>结束时间</h3>
                    <p><input type="date" name="countEnd" id="countEnd" value="" /></p>
                    <h3>代码类型</h3>
                    <p>
                    <div data-role="fieldcontain">
                        <select name="countType" id="countType">
                            <option value="0">仅包含PHP</option>
                            <option value="1">php/js/html/css</option>
                            <option value="2">全部(word/txt等等)</option>
                        </select>
                    </div>
                    </p>
                    <a href="#" data-role="button" data-theme="c" data-icon="search" data-inline="true" id="countSearch">查询</a>
                    <a href="#" data-rel="close" data-role="button" data-theme="c" data-icon="delete" data-inline="true">关闭</a>
                </div>
            </div>

            <div data-role="footer" data-position="fixed">
                <h2>&copy; <a href="mailto:zuojianghua@guanyisoft.com">zuojianghua@guanyisoft.com</a></h2>
            </div>
        </div>


        <!-- 月度报表 --------------------------------------------------->

        <div data-role="page" id="pageCodeList">
            <div data-role="header">
                <h1>代码工作量统计小工具</h1>
                <div data-role="navbar" data-iconpos="left">
                    <ul>
                        <li><a href="#pageCountList" data-icon="grid">SVN工作日志</a></li>
                        <li><a href="#pageCodeList" class="ui-btn-active" data-icon="search">月度报表</a></li>
                        <li><a href="#pageCodeUpdate" data-icon="refresh">更新数据源</a></li>
                        <li><a href="#pageHelp" data-icon="alert">使用帮助</a></li>
                    </ul>
                </div>
            </div>

            <div data-role="content">
                <div id="container" style="min-width: 400px; width: 100%; height: 520px; margin: 0 auto"></div>
            </div>

            <div data-role="footer" data-position="fixed">
                <h2>&copy; <a href="mailto:zuojianghua@guanyisoft.com">zuojianghua@guanyisoft.com</a></h2>
            </div>
        </div>




        <!-- 更新SVN数据页 --------------------------------------------------->

        <div data-role="page" id="pageCodeUpdate">
            <div data-role="header">
                <h1>代码工作量统计小工具</h1>
                <div data-role="navbar" data-iconpos="left">
                    <ul>
                        <li><a href="#pageCountList" data-icon="grid">SVN工作日志</a></li>
                        <li><a href="#pageCodeList" data-icon="search">月度报表</a></li>
                        <li><a href="#pageCodeUpdate" data-icon="refresh" class="ui-btn-active">更新数据源</a></li>
                        <li><a href="#pageHelp" data-icon="alert">使用帮助</a></li>
                    </ul>
                </div>
            </div>

            <div data-role="content">
                <div data-role="collapsible" data-collapsed="false" data-content-theme="d">
                    <h3>更新设置</h3>
                    <table>
                        <thead>
                            <tr>
                                <td><b>更新条件</b></td>
                                <td></td>
                                <td></td>
                            </tr>
                        </thead>
                        <tbody>
                            <tr>
                                <td>起始时间</td>
                                <td><input type="date" data-inline="true" name="updateStart" id="updateStart" value="" /></td>
                                <td></td>
                            </tr>
                            <tr>
                                <td>结束时间</td>
                                <td><input type="date" data-inline="true" name="updateEnd" id="updateEnd" value="" /></td>
                                <td></td>
                            </tr>
                            <tr>
                                <td colspan="3">
                                    <a href="#dialogPage" data-role="button" data-inline="true" data-icon="refresh" data-rel="dialog" id="button_refresh">开始更新</a>
                                    <a href="#" data-role="button" data-inline="true" data-icon="delete" id="button_clear" title="提示：重建本地缓存可能需要很长时间~">删除缓存</a>
                                </td>
                            </tr>
                        </tbody>
                    </table>
                </div>

                <div data-role="collapsible" data-collapsed="false" data-content-theme="d">
                    <h3>可能出错的信息</h3>
                    <ul data-role="listview" data-inset="true" id="ulErrorList">
                    </ul>
                    <a href="#" data-role="button" data-inline="true" data-icon="refresh" id="button_error_refresh">刷新错误</a>
                    <a href="#" data-role="button" data-inline="true" data-icon="delete" id="button_error_clear">清空错误</a>
                </div>

            </div>

            <div data-role="footer" data-position="fixed">
                <h2>&copy; <a href="mailto:zuojianghua@guanyisoft.com">zuojianghua@guanyisoft.com</a></h2>
            </div>
        </div>

        <!-- 帮助页面 -------------------------------------------------------->

        <div data-role="page" id="pageHelp">
            <div data-role="header">
                <h1>代码工作量统计小工具</h1>
                <div data-role="navbar" data-iconpos="left">
                    <ul>
                        <li><a href="#pageCountList" data-icon="grid">SVN工作日志</a></li>
                        <li><a href="#pageCodeList" data-icon="search">月度报表</a></li>
                        <li><a href="#pageCodeUpdate" data-icon="refresh" >更新数据源</a></li>
                        <li><a href="#pageHelp" class="ui-btn-active" data-icon="alert">使用帮助</a></li>
                    </ul>
                </div>
            </div>

            <div data-role="content">
                <div data-role="collapsible-set" data-theme="c" data-content-theme="d">
                    <div data-role="collapsible" data-collapsed="false">
                        <h3>声明</h3>
                        <ul>
                            <li>代码数量不等于代码质量!</li>
                            <li>强烈建议使用Chrome浏览器访问本服务</li>
                            <li>更新数据时，从SVN服务器上下载svn log，更新速度受到svn log导出速度以及网速影响，数据量大时会比较慢，请耐心等待~</li>
                            <li>采用html5 websql存储代码分析后的统计记录。可以删除本地缓存，删除本地缓存后，再次更新将重建</li>
                            <li>有些文本类的文件提交时是以二进制方式提交的，此类文件不能svn diff，另外原本二进制文件（图像、音乐等）或者新建/修改的文件目录本身，代码量统计均为零。因此，本工具统计结果并非100%精确，可能有误差，仅供参考。</li>
                            <li>本工具开源</li>
                        </ul>
                    </div>

                    <div data-role="collapsible">
                        <h3>功能简介</h3>
                        <p>通过服务器svn命令获取svn log，分析每次提交增/删/改的文件，使用svn diff比较每次提交的版本与上一版本之间的代码变动差异，连续增行、减行均记为代码产出行量，单条先减后增（即为修改）记为一行。</p>
                        <p>分析后的统计记录存储在本地websql，字段为：作者、时间、版本号、修订文件、代码产出量</p>
                    </div>

                    <div data-role="collapsible">
                        <h3>关于误差</h3>
                        <p>如果是以二进制方式提交的文本文件，如.php/.html/.js/.css文件，在svn diff时将统计不出来差异信息。此类文件列出在"更新数据源 > 可能出错的信息"列表中，表现为统计的代码量为0，可以手动删除此类文件的svn属性svn:mime-type=application/octet-stream或者更新为text/plain</p>
                        <p>某些第三方公共库或者框架提交时的代码量也被计算，可以在"SVN工作日志 > 统计值修正"中，手动删除。目前发现的第三方代码有：</p>
                        <ul id="ignoreFiles">

                        </ul>
                        <p>如果有遗漏劳烦邮件告知</p>
                        <p>一次提交的单个文件变动量超过1000行也认定为第三方类库。通过以下语句查询到:<br>select a_name, sum(a_code) as total FROM authors where a_code >= 1000 group by a_name order by total desc</p>
                    </div>

                    <div data-role="collapsible">
                        <h3>部署帮助</h3>
                        <p><u>基本设置: </u></p>
                        <ul>
                            <li>$svnurl为可访问的SVN仓库地址</li>
                            <li>$svnname为SVN用户账号</li>
                            <li>$svnpass为SVN用户密码</li>
                            <li>$svncmd为SVN服务器上svn命令路径</li>
                        </ul>
                        <p><u>Unix/Linux: </u></p>
                        <p>
                            需要vim /etc/sudoers给与apache用户执行svn命令的权限，
                            增加以下行（如果apache以www用户运行的）<br>
                            <em>www ALL=(ALL) NOPASSWD: /usr/bin/svn<br>
                                #apache ALL=(ALL) NOPASSWD: /usr/bin/svn<br>
                                Defaults visiblepw</em>
                        </p>
                        <p><u>Windows: </u></p>
                    </div>

                    <div data-role="collapsible">
                        <h3>备注</h3>
                        <p><u>杂: </u></p>
                        <ul>
                            <li>SELECT sum(a_code) FROM authors where a_name = 'zuojh' and datetime(a_time) >= datetime('2013-03-12') and a_files like '%.php' order by a_time</li>
                        </ul>
                    </div>

                </div>
            </div>

            <div data-role="footer" data-position="fixed">
                <h2>&copy; <a href="mailto:zuojianghua@guanyisoft.com">zuojianghua@guanyisoft.com</a></h2>
            </div>
        </div>

        <!-- 数据更新弹出框 --------------------------------------------------->

        <div data-role="page" id="dialogPage">
            <div data-role="header">
                <h2 id="dialogPageHeader">数据更新中</h2>
            </div>
            <div data-role="content">
                <table data-role="table" id="" data-mode="" class="table-stroke">
                    <thead>
                        <tr>
                            <th width="30%">&nbsp;</th>
                            <th>更新进度</th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr>
                            <th>获取SVN日志</th>
                            <td id="refresh_rate_1"></td>
                        </tr>
                        <tr>
                            <th>分析SVN日志</th>
                            <td id="refresh_rate_2"><span id="refresh_rate_2_now">0</span>/<span id="refresh_rate_2_total">0</span></td>
                        </tr>
                        <tr>
                            <th>更新代码量</th>
                            <td id="refresh_rate_3"></td>
                        </tr>
                        <tr>
                            <th>&nbsp;</th>
                            <td></td>
                        </tr>
                    </tbody>
                </table>
            </div>
        </div>

        <!------------------------------------------------------------------->

    </body>
</html>